﻿#ifndef _LeetCodePractice_Solution_1360_H_
#define _LeetCodePractice_Solution_1360_H_

#include <string>
#include <algorithm>
#include <iostream>
#include <assert.h>
using namespace std;

/*
* 请你编写一个程序来计算两个日期之间隔了多少天。

日期以字符串形式给出，格式为 YYYY-MM-DD，如示例所示。

 
示例 1：

输入：date1 = "2019-06-29", date2 = "2019-06-30"
输出：1
示例 2：

输入：date1 = "2020-01-15", date2 = "2019-12-31"
输出：15
*/

namespace Solution_1360
{
	class Solution
	{
		struct Date
		{
			int year = 0;
			int month = 0;
			int day = 0;
		};

		static constexpr int months[12]{
			31,28,31,30,31,30,31,31,30,31,30,31
		};

	public:
		int daysBetweenDates(string date1, string date2)
		{
			Date d1 = ParseDate(date1);
			Date d2 = ParseDate(date2);

			Date* lhs = &d1;
			Date* rhs = &d2;

			if (date1.compare(date2) > 0)
			{
				lhs = &d2;
				rhs = &d1;
			}

			return CalcDaysInterval(lhs, rhs);
		}
	private:
		Date ParseDate(const string& strDate)
		{
			Date date;

			date.year = stoi(strDate.substr(0, 4));

			date.month = stoi(strDate.substr(5, 2));
			date.day = stoi(strDate.substr(8, 2));
			return date;
		}

		bool IsLeapYear(short year)
		{
			//return (year % 4 == 0 && year % 100 != 0);
			if (year % 4 == 0)
			{
				if (year % 100 == 0)
				{
					if (year % 400 == 0)
						return true;
					return false;
				}
				return true;
			}
			return false;
		}

		int CalcDaysInterval(const Date* lhs, const Date* rhs)
		{
			int passed_days = CalcDaysCurrYear(lhs);
			int left_days = CalcDaysCurrYear(rhs);
			if (lhs->year == rhs->year)
				return left_days - passed_days;

			int days = 0;
			if (IsLeapYear(lhs->year))
			{
				days = 366 - passed_days + left_days;
			}
			else
			{
				days = 365 - passed_days + left_days;
			}

			if (lhs->year + 1 == rhs->year)
			{
				return days;
			}

			for (int curr_year = lhs->year + 1; curr_year < rhs->year; ++curr_year)
			{
				int curr_year_days = IsLeapYear(curr_year) ? 366 : 365;
				days += curr_year_days;
			}

			return days;
		}

		int CalcDaysCurrYear(const Date* date)
		{
			int sum = 0;
			for (int i = 0; i < date->month - 1; ++i)
			{
				sum += months[i];
			}
			sum += date->day;
			if (sum > months[0] + months[1] && IsLeapYear(date->year))
				sum += 1;

			return sum;
		}
	};
}

#endif
